package middleware

import (
	"bookmark-web/dao"
	"bookmark-web/utils"
	"fmt"
	"net/http"
	"strconv"
	"strings"

	"github.com/gin-gonic/gin"
)

// JWTAuthMiddleware JWT认证中间件
func JWTAuthMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {

		fmt.Println("开始JWT令牌合法性校验...........")

		// 获取Authorization头
		authHeader := c.GetHeader("Authorization")
		if authHeader == "" {
			// 尝试从Cookie中获取token
			token, err := c.Cookie("token")
			if err != nil || token == "" {
				respondUnauthorized(c, "缺少认证令牌")
				c.Abort()
				return
			}
			authHeader = "Bearer " + token
		}

		// 检查Bearer前缀
		if !strings.HasPrefix(authHeader, "Bearer ") {
			respondUnauthorized(c, "认证令牌格式错误")
			c.Abort()
			return
		}

		// 提取token
		tokenString := strings.TrimPrefix(authHeader, "Bearer ")
		if tokenString == "" {
			respondUnauthorized(c, "认证令牌为空")
			c.Abort()
			return
		}

		// 解析token
		claims, err := utils.ParseToken(tokenString)
		if err != nil {
			respondUnauthorized(c, "无效的认证令牌: "+err.Error())
			c.Abort()
			return
		}

		// 将用户信息存储到上下文中
		c.Set("user_id", claims.UserID)
		c.Set("username", claims.Username)
		c.Set("token", tokenString)

		// 继续处理请求
		c.Next()
	}
}

// OptionalJWTAuthMiddleware 可选的JWT认证中间件（不强制要求token）
func OptionalJWTAuthMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		// 获取Authorization头
		authHeader := c.GetHeader("Authorization")
		if authHeader == "" {
			// 尝试从Cookie中获取token
			token, err := c.Cookie("token")
			if err == nil && token != "" {
				authHeader = "Bearer " + token
			}
		}

		// 如果有token，尝试解析
		if authHeader != "" && strings.HasPrefix(authHeader, "Bearer ") {
			tokenString := strings.TrimPrefix(authHeader, "Bearer ")
			if tokenString != "" {
				claims, err := utils.ParseToken(tokenString)
				if err == nil {
					// 将用户信息存储到上下文中
					c.Set("user_id", claims.UserID)
					c.Set("username", claims.Username)
					c.Set("token", tokenString)
				}
			}
		}

		// 继续处理请求（无论是否有有效token）
		c.Next()
	}
}

// GetUserIDFromContext 从上下文中获取用户ID
func GetUserIDFromContext(c *gin.Context) (uint, bool) {
	userID, exists := c.Get("user_id")
	if !exists {
		return 0, false
	}

	if id, ok := userID.(uint); ok {
		return id, true
	}

	return 0, false
}

// GetUsernameFromContext 从上下文中获取用户名
func GetUsernameFromContext(c *gin.Context) (string, bool) {
	username, exists := c.Get("username")
	if !exists {
		return "", false
	}

	if name, ok := username.(string); ok {
		return name, true
	}

	return "", false
}

// RequireAuth 要求认证的中间件（用于特定路由）
func RequireAuth() gin.HandlerFunc {
	return func(c *gin.Context) {
		userID, exists := GetUserIDFromContext(c)
		if !exists || userID == 0 {
			respondUnauthorized(c, "需要登录后访问")
			c.Abort()
			return
		}
		c.Next()
	}
}

// AdminAuthMiddleware 管理员认证中间件
func AdminAuthMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		// 先检查是否已认证
		userID, exists := GetUserIDFromContext(c)
		if !exists || userID == 0 {
			respondUnauthorized(c, "需要登录后访问")
			c.Abort()
			return
		}

		// 检查用户是否为管理员
		user, err := dao.GetUserByID(strconv.FormatUint(uint64(userID), 10))
		if err != nil {
			respondForbidden(c, "需要管理员权限")
			c.Abort()
			return
		}

		if !user.IsAdmin {
			respondForbidden(c, "需要管理员权限")
			c.Abort()
			return
		}

		c.Next()
	}
}

// CORSMiddleware CORS中间件
func CORSMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		c.Header("Access-Control-Allow-Origin", "*")
		c.Header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
		c.Header("Access-Control-Allow-Headers", "Origin, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")
		c.Header("Access-Control-Allow-Credentials", "true")

		if c.Request.Method == "OPTIONS" {
			c.AbortWithStatus(http.StatusNoContent)
			return
		}

		c.Next()
	}
}

// LoggerMiddleware 日志中间件
func LoggerMiddleware() gin.HandlerFunc {
	return gin.LoggerWithFormatter(func(param gin.LogFormatterParams) string {
		return fmt.Sprintf("%s - [%s] \"%s %s %s %d %s \"%s\" %s\"\n",
			param.ClientIP,
			param.TimeStamp.Format("2006/01/02 - 15:04:05"),
			param.Method,
			param.Path,
			param.Request.Proto,
			param.StatusCode,
			param.Latency,
			param.Request.UserAgent(),
			param.ErrorMessage,
		)
	})
}

// respondUnauthorized 返回未授权响应
func respondUnauthorized(c *gin.Context, message string) {
	c.JSON(http.StatusUnauthorized, utils.Response{
		Code:    401,
		Message: message,
		Data:    nil,
	})
}

// respondForbidden 返回禁止访问响应
func respondForbidden(c *gin.Context, message string) {
	c.JSON(http.StatusForbidden, utils.Response{
		Code:    403,
		Message: message,
		Data:    nil,
	})
}
